import os
from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, pyqtSlot, QUrl
import json
import time
from My_UI import Ui_Form
import sys
import serial
import serial.tools.list_ports


class My_APP(QWidget, Ui_Form):
    def __init__(self):
        super(My_APP, self).__init__()
        self.setupUi(self)
        self.setLayout(self.verticalLayout)
        self.setWindowTitle("飞鸟OTA")
        self.progressBar.setValue(0)

        self.device_id = ""

        self.ser = None

        self.refresh_pushButton.clicked.connect(self.uart_refresh)
        self.uart_read_timer = QTimer()
        self.uart_read_timer.timeout.connect(self.uart_read)
        self.uart_read_timer.start(80)

        self.file_data = []
        self.file_data_size = 0
        self.file_pushButton.clicked.connect(self.choose_file)

        self.download_pushButton.clicked.connect(self.trans_file)

        self.clear_pushButton.clicked.connect(self.clear_record)

    def uart_refresh(self):
        self.uart_comboBox.clear()
        ports = serial.tools.list_ports.comports()
        for port in ports:
            port_name = port.device
            # Windows
            if sys.platform.startswith('win'):
                if port_name.startswith('COM'):
                    self.uart_comboBox.addItem(port_name)
            # Linux/Mac
            else:
                self.uart_comboBox.addItem(port_name)

    def choose_file(self):
        file_filter = "(*.json);;所有文件 (*)"
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            "选择json文件",
            "",
            file_filter
        )

        if file_path:
            self.file_path_lineEdit.setText(file_path)

    def load_file(self):
        try:
            # 清空之前的数据
            self.file_data = []
            with open(self.file_path_lineEdit.text(), "r", encoding='utf-8') as f:
                for line in f:
                    line = line.strip()  # 去除首尾空白字符
                    if line:  # 跳过空行
                        try:
                            # 解析JSON数据
                            json_obj = json.loads(line)
                            self.file_data.append(json_obj)
                        except json.JSONDecodeError as e:
                            self.details_textBrowser.append(f"解析JSON出错: {e}，行内容: {line}")

            self.details_textBrowser.append(f"成功读取文件，共 {len(self.file_data)} 条JSON数据")
            self.file_data_size = self.file_data[0].get("total_size")

        except Exception as e:
            self.details_textBrowser.append(f"读取文件出错: {str(e)}")

    def trans_file(self):
        # 检查是否已选择文件
        if not self.file_path_lineEdit.text():
            self.details_textBrowser.append("请先选择JSON文件")
            return
        self.load_file()
        self.ser = serial.Serial(
                port=self.uart_comboBox.currentText(),
                baudrate=self.baud_comboBox.currentText(),
                bytesize=8,
                parity='N',
                stopbits=1,
                timeout=1,
                write_timeout=1
        )
        start = {
            "type": "uart"
        }
        self.ser.write(json.dumps(start).encode("utf-8"))

    def uart_read(self):
        if self.ser is None:
            return
        if self.ser.is_open:
            bytes_to_read = self.ser.in_waiting
            if bytes_to_read > 0:
                # print(f"检测到{bytes_to_read}字节待读取")
                data = self.ser.readline().decode('utf-8').strip()
                self.details_textBrowser.append(data)
                device_ack = json.loads(data)
                if device_ack.get("type") == "request":
                    self.device_id = device_ack.get("device_id")
                    first_frame = {
                        "type": "start",
                        "device_id": self.device_id,
                        "version": "1.0.1",
                        "file_size": self.file_data_size,
                        "block_size": 256
                    }
                    self.ser.write(json.dumps(first_frame).encode("UTF-8"))
                if device_ack.get("type") == "ack":
                    if device_ack.get("device_id") == self.device_id:
                        if device_ack.get("status") == "ok":
                            if not device_ack.get("end_flag"):
                                seq = device_ack.get("next_seq")
                                if seq == 99999999:
                                    end_signal = {
                                        "type": "end",
                                        "device_id": "CH32_001",
                                        "received_frames": len(self.file_data),
                                        "error_msg": ""
                                    }
                                    self.ser.write(json.dumps(end_signal).encode("UTF-8"))
                                if seq <= len(self.file_data):
                                    # print(self.file_data[seq - 1])
                                    self.ser.write(json.dumps(self.file_data[seq - 1]).encode("UTF-8"))
                                    progress = int(seq / len(self.file_data) * 100)
                                    self.progressBar.setValue(progress)
                        elif device_ack.get("status") == "check_sum_err":
                            self.ser.write(json.dumps(self.file_data[device_ack.get("next_seq") - 1]).encode("UTF-8"))

    def clear_record(self):
        self.progressBar.setValue(0)
        self.details_textBrowser.clear()


if __name__ == '__main__':
    app = QApplication(sys.argv)  # 用于命令行启动传参
    My_window = My_APP()
    My_window.show()
    sys.exit(app.exec_())
